package reader;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Properties;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import utils.MessageUtils;

import news.News;
import news.NewsEvent;

public class Reader implements javax.jms.MessageListener, Runnable {

	private HashMap<String, TopicSubscriber> topicSubscriberMap ; 
	private HashMap<String, News> myNews ;	
	
	private TopicSession pubSession;
	private TopicSession subSession;
	private TopicPublisher publisher;
	private TopicConnection connection;
	private String username;

	private InitialContext jndi;

	/* Constructor. Establish JMS publisher and subscriber */
	public Reader(String username, String password) throws Exception {

		topicSubscriberMap = new HashMap<String, TopicSubscriber>() ;
		myNews = new HashMap<String, News>()  ;
		
		this.username = username;

		// Obtain a JNDI connection
		Properties env = new Properties();
		// ... specify the JNDI properties specific to the vendor
		jndi = new InitialContext(env);
		// Look up a JMS connection factory
		TopicConnectionFactory conFactory = (TopicConnectionFactory) jndi
				.lookup("NewsConnectionFactory");

		// Create a JMS connection
		connection = conFactory.createTopicConnection(username, password);
		connection.setClientID(java.util.UUID.randomUUID().toString());
		
		// Create two JMS session objects
		pubSession = connection.createTopicSession(false,
				Session.AUTO_ACKNOWLEDGE);

		subSession = connection.createTopicSession(false,
				Session.AUTO_ACKNOWLEDGE);

		// // Create a JMS publisher and subscriber
		Topic newsReadTopic = (Topic) jndi.lookup("NewsReadTopic");
		publisher = pubSession.createPublisher(newsReadTopic);

		// Start the JMS connection; allows messages to be delivered
		connection.start();
	}

	public void addTopic(String topicName, String selector) throws NamingException, JMSException {
		// Look up a JMS topic
		Topic chatTopic = (Topic) jndi.lookup(topicName);
		//TopicSubscriber s = subSession.createSubscriber(chatTopic);
	    TopicSubscriber s = subSession.createDurableSubscriber(chatTopic, topicName, selector, true);
		
	    s.setMessageListener(this);
		topicSubscriberMap.put(topicName, s) ;
		
	}

	public void unSubscribe(String topicName) throws JMSException {
		
		topicSubscriberMap.get(topicName).close();
		topicSubscriberMap.remove(topicName);
		subSession.unsubscribe(topicName);
		System.err.println("% "+this.username + " " +"unsubscribed");
	}

	/* Receive message from topic subscriber */
	public void onMessage(Message msg) {
		
		
		try {
			String event = msg.getStringProperty(MessageUtils.NEWS_EVENT);
			String title = msg.getStringProperty(MessageUtils.TITLE);
			String author = msg.getStringProperty(MessageUtils.AUTHOR);
			String datePublished = msg.getStringProperty(MessageUtils.DATE_PUBLISHED);
			String dateModified = msg.getStringProperty(MessageUtils.DATE_MODIFIED);
			String subDomain = msg.getStringProperty(MessageUtils.SUBDOMAIN);
			String content = ((TextMessage) msg).getText() ; 
			
			News n = new News(title, author, Long.parseLong(datePublished), Long.parseLong(dateModified), subDomain, content );
			//System.out.println("Reader " + this.username +" primesc stirea ( " + title + " ) din domeniul  " + subDomain + " (" + event + ")");
			 
			if(event.equals(NewsEvent.NEWS_PUBLISHED)){
				myNews.put(title, n);
				//myNews.add(n);
				System.out.println("---> Reader: " +  this.username  + " news (" + n.getTitle() + ") -- READ");
				publish(author, title);
				
			}
			if(event.equals(NewsEvent.NEWS_MODIFIED)){
				//int i = myNews.
				//myNews.set(i, n);
				myNews.put(title, n);
				System.out.println("---> Reader: " +  this.username  + " news (" + n.getTitle() + ") -- MODIFIED");
				publish(author, title);
				
			}
			if(event.equals(NewsEvent.NEWS_DELETED)){
				//myNews.remove(n);
				myNews.remove(title);
				System.out.println("---> Reader: " +  this.username  + " news (" + n.getTitle() + ") -- DELETED");
			}
	
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
	
	private void publish(String author, String title) {
		Message msg = null; 
			try {
				msg = pubSession.createMessage();
		    	msg.setStringProperty(MessageUtils.AUTHOR, author);
		    	msg.setStringProperty(MessageUtils.NEWS_EVENT,NewsEvent.NEWS_READ);
		    	msg.setStringProperty(MessageUtils.TITLE, title);
		    	//System.out.println("--> Reader " + this.username + " am citit stirea ( " + title + ")");
		    	publisher.publish(msg);
			} catch (JMSException e) {
				e.printStackTrace();
			}
	}

	/* Close the JMS connection */
	private void close() throws JMSException {
		connection.close();
	}

	@Override
	public void run() {
		while (true) {

		}

	}

}
